package com.example.socket.server;

import com.example.socket.core.*;
import com.example.socket.exception.ErrorForwardException;
import com.example.socket.exception.IdentityParameterException;
import com.example.socket.handler.*;
import com.example.socket.parameter.ResultCallback;

/**
 * @author frank
 * 服务器指令分发器
 */
public class ServerDispatcher extends DispatcherSupport {

    private final SyncSupport syncSupport = new SyncSupport();
    private final AsyncSupport asyncSupport = new AsyncSupport();

    @Override
    public void receive(final Message message, final Session session) {
        // 接受到信息事件
        super.receive(message, session);
        if (message.isIgnore()) {
            // 消息已设置忽略标记
            return;
        }
        final Command command = message.getCommand();
        final CommandInfo info = getCommand(command);
        if (info == null || info.getProcessor() == null) {
            logger.warn("通信信息[{}]请求的指令不存在", message);
//			send(commandNotFound(message), session);
            if (session != null) {
                session.close();
            }
            return;
        }

        // 请求的处理
        @SuppressWarnings("rawtypes") final Request request = decodeRequest(message);
        final TypeDefinition definition = info.getDefinition();
        if (definition.isAsync()) {
            asyncSupport.execute(new Runnable() {
                @Override
                public void run() {
                    tryRecieve(session, info, message, request);
                }
            });
        } else if (definition.isSync()) {
            // 方法为同步执行,加入到同步队列执行
            syncSupport.execute(definition.getSyncKey(), new Runnable() {
                @Override
                public void run() {
                    tryRecieve(session, info, message, request);
                }
            });
        } else {
            // 普通请求, 直接执行
            tryRecieve(session, info, message, request);
        }
    }

    /**
     * 捕捉异常处理
     * @param session
     * @param definition
     * @param message
     * @param request
     */
    private void tryRecieve(Session session, CommandInfo info, Message message, Request<?> request) {
        try {
            // 处理请求
            processAsync(request, info, session);
        } catch (ErrorForwardException e) {
            if (logger.isInfoEnabled()) {
                logger.info("socket层业务消息转发", e);
            }
            Object body = e.getBody();
            Command command = Command.valueOf(e.getModule(), e.getCommand());
            Header requestHeader = request.getHeader();
            requestHeader.addState(MessageConstant.STATE_RESPONSE);
            requestHeader.setCommand(command);
            Response<?> response = Response.valueOf(requestHeader, body);
            Message resultMessage = encodeResonse(response);
            send(resultMessage, session);
//		} catch (TypeDefinitionNotFound e) {
//			logger.warn("消息体类型定义不存在", e);
//			send(commandNotFound(message, e), session);
//			destroy(session);
//		} catch (ProcessorNotFound e) {
//			logger.warn("消息处理器不存在", e);
//			send(commandNotFound(message, e), session);
//			destroy(session);
//		} catch (DecodeException e) {
//			logger.warn("接受消息解码异常", e);
//			send(decodeException(message, e), session);
//			destroy(session);
//		} catch (EncodeException e) {
//			logger.warn("发送消息编码异常", e);
//			send(encodeException(message, e), session);
//			destroy(session);
        } catch (IdentityParameterException e) {
            send(identityException(message, e), session);
            logger.warn("会话[{}]身份异常，连接[{}]将被强制关闭", session.getId(), session.getRemoteAddress());
            close(session);
//		} catch (SessionParameterException e) {
//			send(parameterException(message, e), session);
//			logger.warn("会话[{}]SESSION参数异常，连接[{}]将被强制关闭", session.getId(), session.getRemoteAddress());
//			destroy(session);
//		} catch (ProcessingException e) {
//			logger.warn("消息处理逻辑异常", e);
//			send(processingException(message, e), session);
//			destroy(session);
//		} catch (MessageSnException e) {
//			logger.warn("消息SN异常", e);
//			send(msgSnException(message, e), session);
//			destroy(session);
        } catch (Exception e) {
            logger.warn("消息处理未知异常", e);
            send(unknownException(message, e), session);
            close(session);
        }
    }

    private Message identityException(Message message, IdentityParameterException e) {
        message.addState(MessageConstant.IDENTITY_EXCEPTION);
        return message;
    }

    /**
     * 处理请求并返回消息体(不做参数验证)
     * @param request 请求对象
     * @param session 请求会话
     * @return [0]:信息体,[1]:附加信息
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void processAsync(final Request request, final CommandInfo info, final Session session) {
        // 获取请求定义
        final Command command = info.getCommand();
        final Processor<?, ?> processor = info.getProcessor();
        if (logger.isDebugEnabled()) {
            logger.debug("收到指令[{}]请求, 处理器[{}]", command, processor);
        }
        // 结果回调
        ResultCallback callback = new ResponseResultCallback(this, session, request);
        // 处理请求
        processor.process(request, session, callback);
    }

}
